package xlogin

import (
	"time"

	"gitee.com/xiaoyutab/xgotool/https"
	"gitee.com/xiaoyutab/xgotool/optional/xcache"
	"gitee.com/xiaoyutab/xgotool/optional/xnsq"
	"gitee.com/xiaoyutab/xgotool/xerror"
)

type CodeToken struct {
	AppId        string `json:"appid"`         // 用户的APPID，可能为空
	AccessToken  string `json:"access_token"`  // 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
	ExpiresIn    int    `json:"expires_in"`    // 必填，若三方返回的此值json对应错误，请手动重赋值给此值
	RefreshToken string `json:"refresh_token"` // 用户刷新access_token
	Openid       string `json:"openid"`        // 用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID
	Scope        string `json:"scope"`         // 用户授权的作用域，使用逗号（,）分隔
	Unionid      string `json:"unionid"`       // 用户统一标识（针对一个微信开放平台账号下的应用，同一用户的 unionid 是唯一的），只有当scope为"snsapi_userinfo"时返回
	XloginType   uint8  `json:"xlogin_type"`   // 登录类型
}

// 根据code换取token
//
//	code	Code标识
func Code2token(code string, typ uint8) (*CodeToken, error) {
	tokens := CodeToken{}
	var err error
	cache_key := xcache.Key("xlogin.code2token", code, typ)
	if xcache.Exists(cache_key) {
		if err = xcache.GetStruct(cache_key, &tokens); err == nil {
			return &tokens, nil
		}
	}
	// 请求网址获取token
	switch typ {
	case TypesWps:
		err = https.Get("https://openapi.wps.cn/oauthapi/v2/token", map[string]string{
			"appid":  _default.Conf[TypesWps].AppId,
			"appkey": _default.Conf[TypesWps].AppSecret,
			"code":   code,
		}, map[string]string{
			"Content-Type": "application/json",
		}).Json(&tokens, "token")
	case TypesWechat:
		err = https.Get("https://api.weixin.qq.com/sns/oauth2/access_token", map[string]string{
			"appid":      _default.Conf[TypesWechat].AppId,
			"secret":     _default.Conf[TypesWechat].AppSecret,
			"code":       code,
			"grant_type": "authorization_code",
		}, map[string]string{}).Json(&tokens)
	default:
		err = xerror.New("暂不支持该分类")
	}
	if err != nil {
		return nil, err
	}
	if tokens.ExpiresIn == 0 {
		return nil, xerror.New("三方token获取失败")
	}
	tokens.XloginType = typ
	// 存储缓存
	xcache.SetStruct(cache_key, tokens)
	xcache.SetStruct(xcache.Key("xlogin.openid2token", tokens.Openid, typ), tokens)
	// 提前十分钟进行刷新token
	xnsq.SetDef("xlogin.ref-token", tokens, time.Second*time.Duration(tokens.ExpiresIn-600))
	return &tokens, nil
}
